package org.ym.tools;

import org.apache.commons.lang3.StringUtils;

/**
 * @author ym
 * @date 2023-01-31 16:18:12
 */
public class HexTool {
    /**
     * 16进制字符数据组
     */
    private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    /**
     * 16进制字符
     */
    private static final String HEX_STRING = "0123456789ABCDEF";
    /**
     * 数值2
     */
    private static final int INT_2 = 2;

    /**
     * 转16进制
     *
     * @param data 二进制数据
     * @return 16进制数据
     */
    public static String toHexString(byte[] data) {
        if (data == null || data.length == 0) {
            return null;
        }
        StringBuilder stringBuilder = new StringBuilder();
        for(byte b : data){
            stringBuilder.append(HEX_CHAR[(b & 0XF0) >> 4])
                    .append(HEX_CHAR[b & 0X0F]);
        }
        return stringBuilder.toString();
    }

    /**
     * 转16进制
     *
     * @param data 二进制数据
     * @return 16进制数据
     */
    public static String toHexString(byte data) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(HEX_CHAR[(data & 0XF0) >> 4])
                .append(HEX_CHAR[data & 0X0F]);
        return stringBuilder.toString();
    }

    /**
     * 16进制转byte数组
     *
     * @param data 16进制数据
     * @return byte数组
     */
    public static byte[] fromHexString(String data){
        if (StringUtils.isBlank(data)) {
            return new byte[0];
        }
        byte[] result = new byte[data.length() / INT_2];
        char[] dataArr = data.toUpperCase().toCharArray();
        for (int i = 0, len = result.length; i < len; i++) {
            result[i] = (byte) ((Character.digit(dataArr[i* INT_2],16) << 4) | Character.digit(dataArr[i* INT_2 +1],16));
        }
        return result;
    }

    /**
     * 16进制转byte数组
     *
     * @param data 16进制数据
     * @return byte数组
     * @throws HexTransformException 错误
     */
    public static byte[] fromHexStringWithCheck(String data) throws HexTransformException {
        if (StringUtils.isBlank(data)) {
            return new byte[0];
        }
        if (data.length() % INT_2 != 0) {
            throw new HexTransformException("传入的数据不符合16进制要求！");
        }
        byte[] result = new byte[data.length() / INT_2];
        char[] dataArr = data.toUpperCase().toCharArray();
        for (int i = 0, len = result.length; i < len; i++) {
            result[i] = (byte) ((toByte(dataArr[i* INT_2]) << 4) + (toByte(dataArr[i* INT_2 +1] )& 0xff));
        }
        return result;
    }

    /**
     * 转byte
     * @param hexChar 16进制单个字符
     * @return byte
     * @throws HexTransformException 错误
     */
    private static byte toByte(char hexChar) throws HexTransformException {
        byte index = (byte) HEX_STRING.indexOf(hexChar);
        if(index == -1){
            throw new HexTransformException("传入的数据不符合16进制要求！");
        }
        return index;
    }

    protected HexTool(){}

    /**
     * hex转换报错
     */
    private static class HexTransformException extends RuntimeException{
        public HexTransformException() {
        }

        public HexTransformException(String message) {
            super(message);
        }

        public HexTransformException(String message, Throwable cause) {
            super(message, cause);
        }

        public HexTransformException(Throwable cause) {
            super(cause);
        }

        public HexTransformException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
            super(message, cause, enableSuppression, writableStackTrace);
        }
    }
}
